﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using FastDFS.Client;
using Redis.Client;
using FileConvert;
using log4net;
using System.Threading;
namespace ConsoleApplication1
{
    [Serializable]
    class test { public string name { get; set; } }

    public class ScheduleToRedis
    {
        /// <summary>
        /// 任务编号，由客户端生成不重复的号，回调时此参数传给客户端
        /// </summary>
        public string TaskID { get; set; }
        /// <summary>
        /// 转换后的文件格式，目前仅支持到mp4
        /// </summary>
        public string DestFileType { get; set; }
        /// <summary>
        /// 该文件是否加入资源库，取值:true或false,默认为 false-不入库
        /// </summary>
        public bool IsPersistence { get; set; }
        /// <summary>
        /// 接收回调的地址
        /// </summary>
        public string CallBackUrl { get; set; }

        /// <summary>
        /// 是否生成图片，取值:true或false,默认为 false-不生成图
        /// </summary>
        public bool IsCreateImage { get; set; }

        /// <summary>
        /// 客户端可在此字段中传入值，回调时传给客户端
        /// </summary>
        public string Memo { get; set; }

        /// <summary>
        /// 返回数据格式(可选：json 或xml）,默认 json
        /// </summary>
        public string DataLayout { get; set; }

        /// <summary>
        /// 是否及时通知
        /// </summary>
        public bool IsImmediately { get; set; }
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; set; }

        /// <summary>
        /// 本地路径
        /// </summary>
        public string LocalPath { get; set; }
        /// <summary>
        /// ＨＴＴＰ地址
        /// </summary>
        public string Url { get; set; }

        #region 对应的FastDFS配置项
        /// <summary>
        /// DFS服务的Host地址
        /// </summary>
        public string DFSHost { get; set; }
        /// <summary>
        /// DFS服务Prot
        /// </summary>
        public int DFSPort { get; set; }
        /// <summary>
        /// DFS组名
        /// </summary>
        public string DFSGroupName { get; set; }
        #endregion

    }
    /// <summary>
    /// 转换服务器向队列里写（回调列表）
    /// </summary>
    public class TranscodingToSchedule
    {
        /// <summary>
        /// 任务编号，由客户端生成不重复的号，回调时此参数传给客户端
        /// </summary>
        public string TaskID { get; set; }

        /// <summary>
        /// 接收回调的地址
        /// </summary>
        public string CallBackUrl { get; set; }
        /// <summary>
        /// 文件大小　
        /// </summary>
        public Int64 FileSize { get; set; }
        /// <summary>
        /// 转换后的文件时长，单位：秒,非视频文件内容为0
        /// </summary>
        public Int64 FileLength { get; set; }

        /// <summary>
        /// 转码后的地址
        /// </summary>
        public string FileUrl { get; set; }
        /// <summary>
        /// 图片地址
        /// </summary>
        public string GenerateImage { get; set; }


        /// <summary>
        /// 转换后的文件格式，目前仅支持到mp4
        /// </summary>
        public string DestFileType { get; set; }

        /// <summary>
        /// 客户端可在此字段中传入值，回调时传给客户端
        /// </summary>
        public string Memo { get; set; }



        /// <summary>
        /// 转换是否成功 0：失败1：成功
        /// </summary>
        public int Results { get; set; }

        /// 返回数据格式(可选：json 或xml）,默认 json
        /// </summary>
        public string DataLayout { get; set; }

        /// <summary>
        /// 该文件是否加入资源库，取值:true或false,默认为 false-不入库
        /// </summary>
        public bool IsPersistence { get; set; }
    }

    class Foo : IDisposable
    {

        ~Foo()
        {
            // 释放托管的资源
            Dispose(false);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                //正确关闭和释放资源
            }
        }

        #region IDisposable 成员

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);

        }

        #endregion
    }
    abstract class testBase
    {
        protected string a;
        public testBase()
        {
            a = "1";
        }
    }

    class testSub : testBase
    {
        int b;
        public testSub()
        {
            b = 1;
        }
        public void print()
        {
            Console.WriteLine(a);
            Console.WriteLine(b);
        }
    }
    class Program
    {
        /// <summary>
        /// 从DFS下载文件后保存的地址
        /// </summary>
        static string fileSavePath = ConfigurationSettings.AppSettings["OldPath"].ToString();
        /// <summary>
        /// 转码后的文件地址
        /// </summary>
        static string convertFileSavePath = ConfigurationSettings.AppSettings["SavePath"].ToString();


        public Program()
        {

        }
        /// <summary>
        /// 文件下载　
        /// </summary>
        /// <param name="entity"></param>
        static void FileDownLoad(ScheduleToRedis entity)
        {
            var node = FastDFSClient.GetStorageNode(entity.DFSGroupName);
            //#region  从FastDFS中下载文件
            //FDFSFileInfo fileInfo = FastDFSClient.GetFileInfo(node, entity.LocalPath);
            //long step = 8192;
            //if (fileInfo.FileSize >= step)//1K下载
            //{
            //    FileStream fs = new FileStream(fileSavePath + entity.FileName, FileMode.OpenOrCreate, FileAccess.Write);

            //    long offset = 0;
            //    long len = step;
            //    while (len > 0)
            //    {
            //        byte[] buffer = new byte[len];
            //        buffer = FastDFSClient.DownloadFile(node, entity.LocalPath, offset, len);
            //        fs.Write(buffer, 0, int.Parse(len.ToString()));
            //        fs.Flush();
            //        offset = offset + len;
            //        len = (fileInfo.FileSize - offset) >= step ? step : (fileInfo.FileSize - offset);
            //    }
            //    fs.Close();
            //}
            //else//如果文件大小小小于1KB  直接写入文件
            //{
            //    byte[] buffer = new byte[fileInfo.FileSize];
            //    buffer = FastDFSClient.DownloadFile(node, entity.LocalPath);
            //    FileStream fs = new FileStream(fileSavePath + entity.FileName, FileMode.OpenOrCreate, FileAccess.Write);
            //    fs.Write(buffer, 0, buffer.Length);
            //    fs.Flush();
            //    fs.Close();
            //}

            //#endregion

            WebClient web = new WebClient();
            web.DownloadFile(string.Format("http://{0}/{1}/{2}", entity.DFSHost, entity.DFSGroupName, entity.LocalPath), fileSavePath + entity.FileName);

        }
        /// <summary>
        /// 文件上传
        /// </summary>
        /// <param name="entity"></param>
        static string FileUpLoad(ScheduleToRedis entity)
        {
            var node = FastDFSClient.GetStorageNode(entity.DFSGroupName);
            byte[] content = null;
            if (File.Exists(@convertFileSavePath + entity.FileName))
            {
                using (FileStream streamUpload = new FileStream(convertFileSavePath + entity.FileName, FileMode.Open))
                {
                    using (BinaryReader reader = new BinaryReader(streamUpload))
                    {
                        content = reader.ReadBytes((int)streamUpload.Length);
                    }
                    return FastDFSClient.UploadFile(node, content, entity.DestFileType);
                }
            }
            return null;
        }
        /// <summary>
        /// 文件转码
        /// </summary>
        /// <param name="entity"></param>
        static MessageEntity FileConvert(ScheduleToRedis entity)
        {
            return new FileConvertFactory().CreateFileConvert(entity.DestFileType ?? "Mp4")
                .Convert(entity.FileName, true);
        }
        //资源
        static int theResource = 0;
        //读、写操作锁
        static ReaderWriterLock readerWriterLock = new ReaderWriterLock();
        //读数据
        static void Read()
        {
            for (int i = 0; i < 3; i++)
            {
                try
                {
                    //申请读操作锁，如果在1000ms内未获取读操作锁，则放弃
                    readerWriterLock.AcquireReaderLock(1000);
                    Console.WriteLine("开始读取数据，theResource = {0}", theResource);
                    Thread.Sleep(10);
                    Console.WriteLine("读取数据结束，theResource = {0}", theResource);
                    //释放读操作锁
                    readerWriterLock.ReleaseReaderLock();
                }
                catch (ApplicationException)
                {
                    //获取读操作锁失败的处理
                }
            }
        }

        //写数据
        static void Write()
        {
            for (int i = 0; i < 3; i++)
            {
                try
                {
                    //申请写操作锁，如果在1000ms内未获取写操作锁，则放弃
                    readerWriterLock.AcquireWriterLock(1000);
                    Console.WriteLine("开始写数据，theResource = {0}", theResource);
                    //将theResource加1
                    theResource++;
                    Thread.Sleep(100);
                    Console.WriteLine("写数据结束，theResource = {0}", theResource);
                    //释放写操作锁
                    readerWriterLock.ReleaseWriterLock();
                }
                catch (ApplicationException)
                {
                    //获取写操作锁失败
                }
            }
        }
        static void Main(string[] args)
        {

            testSub testsub = new testSub();
            testsub.print();

            var asssembly = (testSub)System.Reflection.Assembly.Load("ConsoleApplication1").CreateInstance("ConsoleApplication1.testSub");
            asssembly.print();
            Console.ReadKey();
            //分别创建2个读操作线程，2个写操作线程，并启动
            Thread tr0 = new Thread(new ThreadStart(Read));
            Thread tr1 = new Thread(new ThreadStart(Read));
            Thread tr2 = new Thread(new ThreadStart(Write));
            Thread tr3 = new Thread(new ThreadStart(Write));

            tr0.Start();
            tr1.Start();
            tr2.Start();
            tr3.Start();

            //等待线程执行完毕
            tr0.Join();
            tr1.Join();
            tr2.Join();
            tr3.Join();

            System.Console.ReadKey();



            #region Hashset(set)
            var Redis1 = RedisManager.GetClient();
            Redis1.SetEntryInHashIfNotExists("users", "001", "001"); //result:001
            Redis1.SetEntryInHashIfNotExists("users", "002", "002"); //result:001,002
            var members = Redis1.GetValueFromHash("users", "003");//result:null
            Redis1.Dispose();
            #endregion

            #region string
            Redis1 = RedisManager.GetClient();
            Redis1.SetEntry("C_User", "1");
            Redis1.SetEntry("C_User", "2");
            var entityStr = Redis1.GetValue("C_User"); //result:2
            Redis1.Dispose();
            #endregion

            #region set 使用了过去的redis.utils组件，每一次socket通讯结果后，自动进行资源回收，关闭socket连接。
            var redisClient1 = new Redis.Utils.RedisClient();//每次socket通讯都要创建一个新实例
            redisClient1.AddToSet("userset", "01");
            Redis1.Dispose();
            redisClient1 = new Redis.Utils.RedisClient();
            redisClient1.AddToSet("userset", "02");
            Redis1.Dispose();
            redisClient1 = new Redis.Utils.RedisClient();
            redisClient1.RemoveFromSet("userset", "01");
            Redis1.Dispose();

            redisClient1 = new Redis.Utils.RedisClient();
            var dd = redisClient1.IsMemberOfSet("userset", "01");
            redisClient1.Dispose();
            #endregion

            #region sort set
            #endregion

            #region list

            #endregion

            Console.Write(members);

            Console.Read();


            var file = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config");
            log4net.Config.XmlConfigurator.Configure(file);
            ILog _log = LogManager.GetLogger("InfoFileAppender");
            _log.Info("info Service Start!");
            _log.Fatal("fatal Service Start!");
            Console.Read();
            /* Redis Test */
            /*先进先出,Enqueue右进，Dequeue左出*/
            /*先进后出 push左进，pop左出*/
            #region 从文件转换队列中得到要转换的对象
            var entity = new ScheduleToRedis();
            using (var redisClient = RedisManager.GetClient())
            {
                using (var redisList = redisClient.GetTypedClient<ScheduleToRedis>())
                {
                    entity = redisList.Lists["FileConvertQueue"].Dequeue();
                }
            }
            #endregion
            if (entity != null)
            {
                #region 视频转换服务

                FileDownLoad(entity);

                var message = FileConvert(entity);

                var fileName = FileUpLoad(entity);

                #region 得到文件大小，然后删除文件
                long fileSize = 0;
                using (var a = File.Open(@convertFileSavePath + entity.FileName, FileMode.Open))
                {
                    fileSize = a.Length;
                }

                // File.Delete(convertFileSavePath + entity.FileName);
                //  File.Delete(fileSavePath + entity.FileName);
                #endregion

                #region 为回调队列赋值
                var result = new TranscodingToSchedule();
                result.Results = message.Result;
                result.CallBackUrl = entity.CallBackUrl;
                result.DataLayout = entity.DataLayout;
                result.DestFileType = entity.DestFileType;
                result.FileLength = message.FileTime;
                result.FileSize = fileSize;
                result.TaskID = entity.TaskID;
                result.FileUrl = string.Format("http://{0}/{1}/{2}"
                    , entity.DFSHost
                    , entity.DFSGroupName
                    , entity.LocalPath);
                result.IsPersistence = entity.IsPersistence;
                result.Memo = message.Message;

                #endregion

                #region 根据entity.IsImmediately判断写回调队列的方式
                if (entity.IsImmediately)
                    using (var redisClient = RedisManager.GetClient())
                    {
                        using (var redisList = redisClient.GetTypedClient<TranscodingToSchedule>())
                        {
                            redisList.Lists["CallbackQueue"].Push(result);
                        }
                    }

                else
                    using (var redisClient = RedisManager.GetClient())
                    {
                        using (var redisList = redisClient.GetTypedClient<TranscodingToSchedule>())
                        {
                            redisList.Lists["CallbackQueue"].Enqueue(result);
                        }
                    }
                #endregion

                #endregion

            }
            Console.ReadKey();
        }
    }
}
